<!DOCTYPE html>
<html lang="en" color-mode="light">

  <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="keywords" content="JavaScript,Hexo" />
  <meta name="author" content="超能虾米" />
  <meta name="description" content="" />
  
  
  <title>
    
      Java多线程 
      
      
      |
    
     超能虾米的博客
  </title>

  
    <link rel="apple-touch-icon" href="/images/favicon.png">
    <link rel="icon" href="/images/favicon.png">
  

  <!-- Raleway-Font -->
  <link href="https://fonts.googleapis.com/css?family=Raleway&display=swap" rel="stylesheet">

  <!-- hexo site css -->
  <link rel="stylesheet" href="/css/main.css" />
  <link rel="stylesheet" href="//at.alicdn.com/t/font_1886449_67xjft27j1l.css" />
  <!-- 代码块风格 -->
  

  <!-- jquery3.3.1 -->
  
    <script defer type="text/javascript" src="/plugins/jquery.min.js"></script>
  

  <!-- fancybox -->
  
    <link href="/plugins/jquery.fancybox.min.css" rel="stylesheet">
    <script defer type="text/javascript" src="/plugins/jquery.fancybox.min.js"></script>
  
  
<script src="/js/fancybox.js"></script>


  

  

  <script>
    var html = document.documentElement
    const colorMode = localStorage.getItem('color-mode')
    if (colorMode) {
      document.documentElement.setAttribute('color-mode', colorMode)
    }
  </script>
<meta name="generator" content="Hexo 5.4.2"><link rel="alternate" href="/atom.xml" title="超能虾米的博客" type="application/atom+xml">
</head>


  <body>
    <div id="app">
      <div class="header">
  <div class="avatar">
    <a href="/">
      <!-- 头像取消懒加载，添加no-lazy -->
      
        <img src="/images/头像.JPEG" alt="">
      
    </a>
    <div class="nickname"><a href="/">超能虾米</a></div>
  </div>
  <div class="navbar">
    <ul>
      
        <li class="nav-item" data-path="/">
          <a href="/">主页</a>
        </li>
      
        <li class="nav-item" data-path="/archives/">
          <a href="/archives/">归档</a>
        </li>
      
        <li class="nav-item" data-path="/categories/">
          <a href="/categories/">分类</a>
        </li>
      
        <li class="nav-item" data-path="/tags/">
          <a href="/tags/">标签</a>
        </li>
      
        <li class="nav-item" data-path="/friends/">
          <a href="/friends/">朋友</a>
        </li>
      
        <li class="nav-item" data-path="/about/">
          <a href="/about/">关于我</a>
        </li>
      
    </ul>
  </div>
</div>


<script src="/js/activeNav.js"></script>



      <div class="flex-container">
        <!-- 文章详情页，展示文章具体内容，url形式：https://yoursite/文章标题/ -->
<!-- 同时为「标签tag」，「朋友friend」，「分类categories」，「关于about」页面的承载页面，具体展示取决于page.type -->


  <!-- LaTex Display -->

  
    <script async type="text/javascript" src="/plugins/mathjax/tex-chtml.js"></script>
  
  <script>
    MathJax = {
      tex: {
        inlineMath: [['$', '$'], ['\\(', '\\)']]
      }
    }
  </script>





  <!-- clipboard -->

  
    <script async type="text/javascript" src="/plugins/clipboard.min.js"></script>
  
  
<script src="/js/codeCopy.js"></script>







  

  

  

  
  <!-- 文章内容页 url形式：https://yoursite/文章标题/ -->
  <div class="container post-details" id="post-details">
    <div class="post-content">
      <div class="post-title">Java多线程</div>
      <div class="post-attach">
        <span class="post-pubtime">
          <i class="iconfont icon-updatetime mr-10" title="Update time"></i>
          2021-08-23 16:16:54
        </span>
        
              <span class="post-categories">
                <i class="iconfont icon-bookmark" title="Categories"></i>
                
                <span class="span--category">
                  <a href="/categories/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" title="多线程">
                    <b>#</b> 多线程
                  </a>
                </span>
                
                <span class="span--category">
                  <a href="/categories/%E5%A4%9A%E7%BA%BF%E7%A8%8B/Java/" title="Java">
                    <b>#</b> Java
                  </a>
                </span>
                
                <span class="span--category">
                  <a href="/categories/%E5%A4%9A%E7%BA%BF%E7%A8%8B/Java/%E5%90%8E%E7%AB%AF/" title="后端">
                    <b>#</b> 后端
                  </a>
                </span>
                
                <span class="span--category">
                  <a href="/categories/%E5%A4%9A%E7%BA%BF%E7%A8%8B/Java/%E5%90%8E%E7%AB%AF/Java/" title="Java">
                    <b>#</b> Java
                  </a>
                </span>
                
              </span>
          
              <span class="post-tags">
                <i class="iconfont icon-tags mr-10" title="Tags"></i>
                
                <span class="span--tag mr-8">
                  <a href="/tags/Java/" title="Java">
                    #Java
                  </a>
                </span>
                
                <span class="span--tag mr-8">
                  <a href="/tags/%E5%B7%A5%E5%85%B7/" title="工具">
                    #工具
                  </a>
                </span>
                
                <span class="span--tag mr-8">
                  <a href="/tags/%E7%AE%97%E6%B3%95/" title="算法">
                    #算法
                  </a>
                </span>
                
                <span class="span--tag mr-8">
                  <a href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" title="多线程">
                    #多线程
                  </a>
                </span>
                
              </span>
          
      </div>
      <div class="markdown-body">
        <p>[TOC]</p>
<h1 id="线程的创建和启动"><a href="#线程的创建和启动" class="headerlink" title="线程的创建和启动"></a>线程的创建和启动</h1><h2 id="多线程实现的原理"><a href="#多线程实现的原理" class="headerlink" title="多线程实现的原理"></a>多线程实现的原理</h2><ul>
<li>Java语言的JVM允许程序运行多个线程，多线程可以通过Java中的java.lang.Thread类来体现。</li>
<li>Thread类的特性<ul>
<li>每个线程都是通过某个特定的Thread对象的run()方法来完成操作的，经常吧run()方法的主体称为线程体。</li>
<li>通过Thread方法的start()方法来启动这个线程，而非直接调用run()。</li>
</ul>
</li>
</ul>
<h2 id="方式一：继承于Thread类"><a href="#方式一：继承于Thread类" class="headerlink" title="方式一：继承于Thread类"></a>方式一：继承于Thread类</h2><ol>
<li>创建一个继承于Thread类的子类。</li>
<li>重写Thread类的run()方法。</li>
<li>创建Thread类的子类的对象。</li>
<li>通过此对象调用start()来启动一个线程。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThreadTest</span> <span class="keyword">extends</span> <span class="title class_">Thread</span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="comment">//线程体,启动线程时会运行run()方法中的代码</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//输出100以内的偶数</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (i % <span class="number">2</span> == <span class="number">0</span>)&#123;</span><br><span class="line">                System.out.println(Thread.currentThread().getName()+<span class="string">&quot;:\t&quot;</span>+i);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">//创建一个Thread类的子类对象</span></span><br><span class="line">        <span class="type">ThreadTest</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ThreadTest</span>();</span><br><span class="line">        <span class="comment">//通过此对象调用start()启动一个线程</span></span><br><span class="line">        t1.start();</span><br><span class="line">        <span class="comment">//注意:已经启动过一次的线程无法再次启动</span></span><br><span class="line">        <span class="comment">//再创建一个线程</span></span><br><span class="line">        <span class="type">ThreadTest</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ThreadTest</span>();</span><br><span class="line">        t2.start();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//另一种调用方法,此方法并没有给对象命名</span></span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">ThreadTest</span>().start();</span><br><span class="line"></span><br><span class="line">        System.out.println(<span class="string">&quot;主线程&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="方式一：创建Thread匿名子类（也属于方法一）"><a href="#方式一：创建Thread匿名子类（也属于方法一）" class="headerlink" title="方式一：创建Thread匿名子类（也属于方法一）"></a>方式一：创建Thread匿名子类（也属于方法一）</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AnonymousSubClass</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">Thread</span>()&#123;</span><br><span class="line">            <span class="meta">@Override</span></span><br><span class="line">            <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">                <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (i % <span class="number">2</span> == <span class="number">0</span>) System.out.println(Thread.currentThread().getName() + <span class="string">&quot;:\t&quot;</span> + i);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;.start();</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="方式二：实现Runnable接口"><a href="#方式二：实现Runnable接口" class="headerlink" title="方式二：实现Runnable接口#"></a>方式二：实现Runnable接口<a target="_blank" rel="noopener" href="https://www.cnblogs.com/13roky/p/14707360.html#24-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%88%9B%E5%BB%BA%EF%BC%8C%E6%96%B9%E5%BC%8F%E4%BA%8C%EF%BC%9A%E5%AE%9E%E7%8E%B0runnable%E6%8E%A5%E5%8F%A3">#</a></h2><ol>
<li>创建一个实现Runnable接口的类。</li>
<li>实现类去实现Runnable接口中的抽象方法：run()。</li>
<li>创建实现类的对象。</li>
<li>将此对象作为参数传到Thread类的构造器中，创建Thread类的对象。</li>
<li>通过Thread类的对象调用start()方法。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">RunnableThread</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">//创建实现类的对象</span></span><br><span class="line">        <span class="type">RunnableThread01</span> <span class="variable">runnableThread01</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">RunnableThread01</span>();</span><br><span class="line">        <span class="comment">//创建Thread类的对象,并将实现类的对象当做参数传入构造器</span></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(runnableThread01);</span><br><span class="line">        <span class="comment">//使用Thread类的对象去调用Thread类的start()方法:①启动了线程 ②Thread中的run()调用了Runnable中的run()</span></span><br><span class="line">        t1.start();</span><br><span class="line"></span><br><span class="line">        <span class="comment">//在创建一个线程时，只需要new一个Thread类就可,不需要new实现类</span></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">t2</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Thread</span>(runnableThread01);</span><br><span class="line">        t2.start();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//RunnableThread01实现Runnable接口的run()抽象方法</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">RunnableThread01</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (i % <span class="number">2</span> == <span class="number">0</span>) System.out.println(Thread.currentThread().getName() + <span class="string">&quot;:\t&quot;</span> + i);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="比较创建线程的两种方式"><a href="#比较创建线程的两种方式" class="headerlink" title="比较创建线程的两种方式"></a>比较创建线程的两种方式</h3><ul>
<li>Java中只允许单进程，以卖票程序TiketSales类来说，很有可能这个类本来就有父类，这样一来就不可以继承Thread类来完成多线程了，但是一个类可以实现多个接口，因此实现的方式没有类的单继承性的局限性，用实现Runnable接口的方式来完成多线程更加实用。</li>
<li>实现Runnable接口的方式天然具有共享数据的特性（不用static变量）。因为继承Thread的实现方式，需要创建多个子类的对象来进行多线程，如果子类中有变量A，而不使用static约束变量的话，每个子类的对象都会有自己独立的变量A，只有static约束A后，子类的对象才共享变量A。而实现Runnable接口的方式，只需要创建一个实现类的对象，要将这个对象传入Thread类并创建多个Thread类的对象来完成多线程，而这多个Thread类对象实际上就是调用一个实现类对象而已。实现的方式更适合来处理多个线程有共享数据的情况。</li>
<li>联系：Thread类中也实现了Runnable接口</li>
<li>相同点两种方式都需要重写run()方法，线程的执行逻辑都在run()方法中</li>
</ul>
<h2 id="方式三：实现Callable接口"><a href="#方式三：实现Callable接口" class="headerlink" title="方式三：实现Callable接口"></a>方式三：实现Callable接口</h2><p><strong>与Runnable相比，Callable功能更强大</strong></p>
<ol>
<li>相比run()方法，可以有返回值</li>
<li>方法可以抛出异常</li>
<li>支持泛型的返回值</li>
<li>需要借助FutureTask类，比如获取返回结果</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//1.创建一个实现Callable的实现类</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">NumThread</span> <span class="keyword">implements</span> <span class="title class_">Callable</span>&lt;Integer&gt;&#123;</span><br><span class="line">    <span class="comment">//2.实现call方法，将此线程需要执行的操作声明在call()中</span></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Integer <span class="title function_">call</span><span class="params">()</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="type">int</span> <span class="variable">sum</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">1</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span>(i%<span class="number">2</span>==<span class="number">0</span>)&#123;</span><br><span class="line">                System.out.println(i);</span><br><span class="line">                sum += i;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> sum;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThreadNew</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        <span class="comment">//3.创建Callable接口实现类的对象</span></span><br><span class="line">        <span class="type">NumThread</span> <span class="variable">numThread</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">NumThread</span>();</span><br><span class="line">        <span class="comment">//4.将此Callable接口实现类的对象作为参数传递到FutureTask构造器中，创建FutureTask对象</span></span><br><span class="line">        FutureTask&lt;Integer&gt; futureTask = <span class="keyword">new</span> <span class="title class_">FutureTask</span>(numThread);</span><br><span class="line">        <span class="comment">//5.将FutureTask的对象作为参数传递到Thread类的构造器中，创建Thread对象，并调用start()</span></span><br><span class="line">        <span class="keyword">new</span> <span class="title class_">Thread</span>(futureTask).start();</span><br><span class="line"></span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">//6.获取Callable中Call方法的返回值</span></span><br><span class="line">            <span class="type">Integer</span> <span class="variable">sum</span> <span class="operator">=</span> futureTask.get();</span><br><span class="line">            System.out.println(<span class="string">&quot;总和为&quot;</span>+sum);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125; <span class="keyword">catch</span> (ExecutionException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="方式四：线程池"><a href="#方式四：线程池" class="headerlink" title="方式四：线程池"></a>方式四：线程池</h2><p><strong>背景：</strong></p>
<p> 经常创建和销毁、使用量特别大的资源、比如并发情况下的线程、对性能影响很大。</p>
<p><strong>思路：</strong></p>
<p> 提前创建好多个线程，放入线程池中，使用时直接获取，使用完放回池中。可以避免频繁创建销毁、实现重复利用。类似生活中的公共交通工具。</p>
<p><strong>优点：</strong></p>
<p> 提高响应速度（减少了创建新线程的时间）</p>
<p> 降低资源消耗（重复利用线程池中线程，不需要每次都创建）</p>
<p> 便于线程管理</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">NumberThread</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; i &lt; <span class="number">100</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">if</span> (i % <span class="number">2</span> == <span class="number">0</span>) &#123;</span><br><span class="line">                System.out.println(Thread.currentThread().getName() + <span class="string">&quot;:\t&quot;</span> + i);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ThreadPool</span> &#123;</span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line"></span><br><span class="line">        <span class="comment">//1.提供指定线程数量的线程池</span></span><br><span class="line">        <span class="type">ExecutorService</span> <span class="variable">service</span> <span class="operator">=</span> Executors.newFixedThreadPool(<span class="number">10</span>);</span><br><span class="line">        <span class="type">ThreadPoolExecutor</span> <span class="variable">service1</span> <span class="operator">=</span> (ThreadPoolExecutor) service;</span><br><span class="line">        <span class="comment">//设置线程池的属性</span></span><br><span class="line">        <span class="comment">//        System.out.println(service.getClass());</span></span><br><span class="line">        <span class="comment">//        service1.setCorePoolSize(15);</span></span><br><span class="line">        <span class="comment">//        service1.setKeepAliveTime();</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//2.执行指定的线程的操作。需要提供实现Runnable接口或Callable接口实现类的对象。</span></span><br><span class="line">        service.execute(<span class="keyword">new</span> <span class="title class_">NumberThread</span>()); <span class="comment">//适合用于Runnable</span></span><br><span class="line">        <span class="comment">//        service.submit(); 适合适用于Callable</span></span><br><span class="line">        <span class="comment">//关闭线程池</span></span><br><span class="line">        service.shutdown();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="方式五：CompletableFuture"><a href="#方式五：CompletableFuture" class="headerlink" title="方式五：CompletableFuture"></a>方式五：CompletableFuture</h2><p>见[[JUC笔记]]</p>
<h1 id="Thread类的常用方法"><a href="#Thread类的常用方法" class="headerlink" title="Thread类的常用方法"></a>Thread类的常用方法</h1><ul>
<li>start() : 启动当前线程, 调用当前线程的run()方法</li>
<li>run() : 通常需要重写Thread类中的此方法, 将创建的线程要执行的操作声明在此方法中</li>
<li>currentThread() : 静态方法, 返回当前代码执行的线程</li>
<li>getName() : 获取当前线程的名字</li>
<li>setName() : 设置当前线程的名字</li>
<li>yield() : 释放当前CPU的执行权</li>
<li>join() : 在线程a中调用线程b的join(), 此时线程a进入阻塞状态, 知道线程b完全执行完以后, 线程a才结束阻塞状态</li>
<li>stop() : 已过时. 当执行此方法时,强制结束当前线程.</li>
<li>sleep(long militime) : 让线程睡眠指定的毫秒数，在指定时间内，线程是阻塞状态</li>
<li>isAlive() ：判断当前线程是否存活</li>
</ul>
<h1 id="线程的调度"><a href="#线程的调度" class="headerlink" title="线程的调度"></a>线程的调度</h1><h2 id="cpu的调度策略"><a href="#cpu的调度策略" class="headerlink" title="cpu的调度策略"></a>cpu的调度策略</h2><ul>
<li><strong>时间片</strong></li>
<li><strong>抢占式：</strong>高优先级的线程抢占cpu。</li>
</ul>
<h2 id="Java的调度算法："><a href="#Java的调度算法：" class="headerlink" title="Java的调度算法："></a>Java的调度算法：</h2><ul>
<li>同优先级线程组成先进先出队列（先到先服务），使用时间片策略。</li>
<li>堆高优先级，使用优先调度的抢占式策略。</li>
</ul>
<p><strong>线程的优先级等级</strong>（一共有10挡）</p>
<ul>
<li>MAX_PRIORITY：10</li>
<li>MIN_PRIORITY：1</li>
<li>NORM_PRIORITY：5 (默认优先级)</li>
</ul>
<p><strong>获取和设置当前线程的优先级</strong></p>
<ul>
<li><code>getPriority();</code> 获取</li>
<li><code>setPriority(int p);</code> 设置</li>
</ul>
<p><strong>说明：高优先级的线程要抢占低优先级线程cpu的执行权。但是只是从概率上讲，高优先级的线程高概率的情况下被执行。并不意味着只有高优先级的线程执行完成以后，低优先级的线程才执行。</strong></p>
<h1 id="线程的生命周期"><a href="#线程的生命周期" class="headerlink" title="线程的生命周期"></a>线程的生命周期</h1><ul>
<li>JDk中用Thread.State类定义了线程的几种状态</li>
</ul>
<p><img src="https://i.vgy.me/qiV0by.png" alt="线程的声明周期"></p>
<h1 id="线程同步问题解决"><a href="#线程同步问题解决" class="headerlink" title="线程同步问题解决"></a>线程同步问题解决</h1><h2 id="方式一：同步代码块"><a href="#方式一：同步代码块" class="headerlink" title="方式一：同步代码块"></a>方式一：同步代码块</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">synchronized</span>(同步监视器)&#123;需要被同步的代码&#125;</span><br></pre></td></tr></table></figure>

<p>说明：</p>
<ol>
<li>操作共享数据（多个线程共同操作的变量）的代码，即为需要被同步的代码。 不能多包涵代码（效率低，如果包到while前面就变成了单线程了），也不能少包含代码</li>
<li>共享数据：多个线程共同操作的变量。</li>
<li>同步监视器：俗称，锁。任何一个类的对象都可以充当锁。但是所有的线程都必须共用一把锁，共用一个对象。</li>
</ol>
<p>锁的选择：</p>
<ol>
<li><p>自行创建，共用对象，如下面demo中的Object对象。</p>
</li>
<li><p>使用this表示当前类的对象</p>
<p>继承Thread的方法中的锁不能使用this代替，因为继承thread实现多线程时，会创建多个子类对象来代表多个线程，这个时候this指的时当前这个类的多个对象，不唯一，无法当作锁。</p>
<p>实现Runnable接口的方式中，this可以当作锁，因为这种方式只需要创建一个实现类的对象，将实现类的对象传递给多个Thread类对象来当作多个线程，this就是这个一个实现类的对象，是唯一的，被所有线程所共用的对象。</p>
</li>
<li><p>使用类当作锁，以下面demo为例，其中的锁可以写为<code>WindowThread.class</code>, 从这里可以得出结论，类也是一个对象</p>
</li>
</ol>
<p>优点：同步的方式，解决了线程安全的问题</p>
<p>缺点：操作同步代码时，只能有一个线程参与，其他线程等待。相当于时一个单线程的过程，效率低。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">WindowThread</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">tiketsNum</span> <span class="operator">=</span> <span class="number">100</span>;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">//由于，Runnable实现多线程，所有线程共用一个实现类的对象，所以三个线程都共用实现类中的这个Object类的对象。</span></span><br><span class="line">    <span class="type">Object</span> <span class="variable">obj</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Object</span>();</span><br><span class="line">    <span class="comment">//如果时继承Thread类实现多线程，那么需要使用到static Object obj = new Object();</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//Object obj = new Object();</span></span><br><span class="line">        <span class="comment">//如果Object对象在run()方法中创建，那么每个线程运行都会生成自己的Object类的对象，并不是三个线程的共享对象，所以并没有给加上锁。</span></span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (obj) &#123;</span><br><span class="line">                <span class="keyword">if</span> (tiketsNum &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        <span class="comment">//手动让线程进入阻塞,增大安全性发生的概率</span></span><br><span class="line">                        Thread.sleep(<span class="number">100</span>);</span><br><span class="line">                    &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                        e.printStackTrace();</span><br><span class="line">                    &#125;</span><br><span class="line">                    System.out.println(Thread.currentThread().getName() + <span class="string">&quot;:\t票号:&quot;</span> + tiketsNum + <span class="string">&quot;\t剩余票数:&quot;</span> + --tiketsNum);</span><br><span class="line">                &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="方式二：同步方法"><a href="#方式二：同步方法" class="headerlink" title="方式二：同步方法"></a>方式二：同步方法</h2><p>将所要同步的代码放到一个方法中，将方法声明为synchronized同步方法。之后可以在run()方法中调用同步方法。</p>
<p><strong>要点：</strong></p>
<ol>
<li>同步方法仍然涉及到同步监视器，只是不需要我们显示的声明。</li>
<li>非静态的同步方法，同步监视器是：this。</li>
<li>静态的同步方法，同步监视器是：当前类本身。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Window02Thread</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">tiketsNum</span> <span class="operator">=</span> <span class="number">100</span>;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">while</span> (tiketsNum &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            show();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">show</span><span class="params">()</span> &#123; <span class="comment">//同步监视器：this</span></span><br><span class="line">        <span class="keyword">if</span> (tiketsNum &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">//手动让线程进入阻塞,增大安全性发生的概率</span></span><br><span class="line">                Thread.sleep(<span class="number">100</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;:\t票号:&quot;</span> + tiketsNum + <span class="string">&quot;\t剩余票数:&quot;</span> + --tiketsNum);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">synchronized</span> <span class="keyword">void</span> <span class="title function_">show</span><span class="params">()</span> &#123;<span class="comment">//同步监视器：Winddoe03Thread.class  不加static话同步监视器为t1 t2 t3所以错误</span></span><br><span class="line">        <span class="keyword">if</span> (tiketsNum &gt; <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">//手动让线程进入阻塞,增大安全性发生的概率</span></span><br><span class="line">                Thread.sleep(<span class="number">100</span>);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125;</span><br><span class="line">            System.out.println(Thread.currentThread().getName() + <span class="string">&quot;:\t票号:&quot;</span> + tiketsNum + <span class="string">&quot;\t剩余票数:&quot;</span> + --tiketsNum);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="使用同步解决懒汉模式的线程安全问题"><a href="#使用同步解决懒汉模式的线程安全问题" class="headerlink" title="使用同步解决懒汉模式的线程安全问题"></a>使用同步解决懒汉模式的线程安全问题</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Bank</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="title function_">Bank</span><span class="params">()</span> &#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">Bank</span> <span class="variable">instance</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> Bank <span class="title function_">getInstance</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">//方式一：效率性差，每个等待线程都会进入同步代码块</span></span><br><span class="line">        <span class="comment">//        synchronized (Bank.class) &#123;</span></span><br><span class="line">        <span class="comment">//            if (instance == null) &#123;</span></span><br><span class="line">        <span class="comment">//                instance = new Bank();</span></span><br><span class="line">        <span class="comment">//            &#125;</span></span><br><span class="line">        <span class="comment">//        &#125;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">//方式二：在同步代码块外层在判断一次，就防止所有线程进入同步代码块。</span></span><br><span class="line">        <span class="keyword">if</span> (instance == <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="keyword">synchronized</span> (Bank.class) &#123;</span><br><span class="line">                <span class="keyword">if</span> (instance == <span class="literal">null</span>) &#123;</span><br><span class="line">                    instance = <span class="keyword">new</span> <span class="title class_">Bank</span>();</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> instance;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="方式三：Lock锁-JDK5-0新特性"><a href="#方式三：Lock锁-JDK5-0新特性" class="headerlink" title="方式三：Lock锁 -JDK5.0新特性#"></a>方式三：Lock锁 -JDK5.0新特性<a target="_blank" rel="noopener" href="https://www.cnblogs.com/13roky/p/14707360.html#623-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98%E7%9A%84%E8%A7%A3%E5%86%B3%E6%96%B9%E5%BC%8F%E4%BA%8C%EF%BC%9Alock%E9%94%81--jdk50%E6%96%B0%E7%89%B9%E6%80%A7">#</a></h2><p>JDK5.0之后，可以通过实例化ReentrantLock对象，在所需要同步的语句前，调用ReentrantLock对象的lock()方法，实现同步锁，在同步语句结束时，调用unlock()方法结束同步锁</p>
<p><strong>synchronized和lock的异同：(面试题)</strong></p>
<figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">1.</span> Lcok是显式锁（需要手动开启和关闭锁），synchronized是隐式锁，除了作用域自动释放。</span><br><span class="line"><span class="bullet">2.</span> Lock只有代码块锁，synchronized有代码块锁和方法锁。</span><br><span class="line"><span class="bullet">3.</span> 使用Lcok锁，JVM将花费较少的时间来调度线程，性能更好。并且具有更好的拓展性（提供更多的子类）</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">SafeLockThread</span> <span class="keyword">implements</span> <span class="title class_">Runnable</span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="variable">tickets</span> <span class="operator">=</span> <span class="number">100</span>;</span><br><span class="line">    <span class="keyword">private</span> <span class="type">ReentrantLock</span> <span class="variable">lock</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">ReentrantLock</span>();</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">run</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">while</span> (tickets&gt;<span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="comment">//在这里锁住，有点类似同步监视器</span></span><br><span class="line">                lock.lock();</span><br><span class="line">                <span class="keyword">if</span> (tickets &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                    Thread.sleep(<span class="number">100</span>);</span><br><span class="line">                    System.out.println(Thread.currentThread().getName() + <span class="string">&quot;:\t票号:&quot;</span> + tickets + <span class="string">&quot;\t剩余票数:&quot;</span> + --tickets);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">catch</span> (InterruptedException e) &#123;</span><br><span class="line">                e.printStackTrace();</span><br><span class="line">            &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                <span class="comment">//操作完成共享数据后在这里解锁</span></span><br><span class="line">                lock.unlock();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="线程的通信"><a href="#线程的通信" class="headerlink" title="线程的通信"></a>线程的通信</h1><p><strong>所用的到方法：</strong></p>
<p> wait()：一旦执行此方法，当前线程就会进入阻塞，一旦执行wait()会释放同步监视器。</p>
<p> notify()：一旦执行此方法，将会唤醒被wait的一个线程。如果有多个线程被wait，就唤醒优先度最高的。</p>
<p> notifyAll() ：一旦执行此方法，就会唤醒所有被wait的线程</p>
<p><strong>说明：</strong></p>
<p> 这三个方法必须在同步代码块或同步方法中使用。</p>
<p> 三个方法的调用者必须是同步代码块或同步方法中的同步监视器。</p>
<p> 这三个方法并不时定义在Thread类中的，而是定义在Object类当中的。因为所有的对象都可以作为同步监视器，而这三个方法需要由同步监视器调用，所以任何一个类都要满足，那么只能写在Object类中。</p>
<p><strong>sleep()和wait()的异同：(面试题)</strong></p>
<ol>
<li><p>相同点：两个方法一旦执行，都可以让线程进入阻塞状态。</p>
</li>
<li><p>不同点：1) 两个方法声明的位置不同：Thread类中声明sleep(),Object类中声明wait()</p>
<ol start="2">
<li><p>调用要求不同：sleep()可以在任何需要的场景下调用。wait()必须在同步代码块中调用。</p>
</li>
<li><p>关于是否释放同步监视器：如果两个方法都使用在同步代码块呵呵同步方法中，sleep不会释放锁，wait会释放锁。</p>
</li>
</ol>
</li>
</ol>
<p>[参考来源](<a target="_blank" rel="noopener" href="https://www.cnblogs.com/13roky/p/14707360.html">Java多线程详解——一篇文章搞懂Java多线程 - 13roky - 博客园 (cnblogs.com)</a>)</p>

      </div>
      
        <div class="prev-or-next">
          <div class="post-foot-next">
            
              <a href="/2021/08/04/%E5%90%8E%E7%AB%AF/Spring%20Cloud/Spring-Cloud%E7%AC%94%E8%AE%B0/" target="_self">
                <i class="iconfont icon-chevronleft"></i>
                <span>Prev</span>
              </a>
            
          </div>
          <div class="post-attach">
            <span class="post-pubtime">
              <i class="iconfont icon-updatetime mr-10" title="Update time"></i>
              2021-08-23 16:16:54
            </span>
            
                  <span class="post-categories">
                    <i class="iconfont icon-bookmark" title="Categories"></i>
                    
                    <span class="span--category">
                      <a href="/categories/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" title="多线程">
                        <b>#</b> 多线程
                      </a>
                    </span>
                    
                    <span class="span--category">
                      <a href="/categories/%E5%A4%9A%E7%BA%BF%E7%A8%8B/Java/" title="Java">
                        <b>#</b> Java
                      </a>
                    </span>
                    
                    <span class="span--category">
                      <a href="/categories/%E5%A4%9A%E7%BA%BF%E7%A8%8B/Java/%E5%90%8E%E7%AB%AF/" title="后端">
                        <b>#</b> 后端
                      </a>
                    </span>
                    
                    <span class="span--category">
                      <a href="/categories/%E5%A4%9A%E7%BA%BF%E7%A8%8B/Java/%E5%90%8E%E7%AB%AF/Java/" title="Java">
                        <b>#</b> Java
                      </a>
                    </span>
                    
                  </span>
              
                  <span class="post-tags">
                    <i class="iconfont icon-tags mr-10" title="Tags"></i>
                    
                    <span class="span--tag mr-8">
                      <a href="/tags/Java/" title="Java">
                        #Java
                      </a>
                    </span>
                    
                    <span class="span--tag mr-8">
                      <a href="/tags/%E5%B7%A5%E5%85%B7/" title="工具">
                        #工具
                      </a>
                    </span>
                    
                    <span class="span--tag mr-8">
                      <a href="/tags/%E7%AE%97%E6%B3%95/" title="算法">
                        #算法
                      </a>
                    </span>
                    
                    <span class="span--tag mr-8">
                      <a href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" title="多线程">
                        #多线程
                      </a>
                    </span>
                    
                  </span>
              
          </div>
          <div class="post-foot-prev">
            
              <a href="/2021/08/23/%E5%90%8E%E7%AB%AF/%E4%B8%AD%E9%97%B4%E4%BB%B6/Rabbitmq%E7%AC%94%E8%AE%B0/" target="_self">
                <span>Next</span>
                <i class="iconfont icon-chevronright"></i>
              </a>
            
          </div>
        </div>
      
    </div>
    
  <div id="btn-catalog" class="btn-catalog">
    <i class="iconfont icon-catalog"></i>
  </div>
  <div class="post-catalog hidden" id="catalog">
    <div class="title">Contents</div>
    <div class="catalog-content">
      
        <ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%88%9B%E5%BB%BA%E5%92%8C%E5%90%AF%E5%8A%A8"><span class="toc-text">线程的创建和启动</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%A4%9A%E7%BA%BF%E7%A8%8B%E5%AE%9E%E7%8E%B0%E7%9A%84%E5%8E%9F%E7%90%86"><span class="toc-text">多线程实现的原理</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E5%BC%8F%E4%B8%80%EF%BC%9A%E7%BB%A7%E6%89%BF%E4%BA%8EThread%E7%B1%BB"><span class="toc-text">方式一：继承于Thread类</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E5%BC%8F%E4%B8%80%EF%BC%9A%E5%88%9B%E5%BB%BAThread%E5%8C%BF%E5%90%8D%E5%AD%90%E7%B1%BB%EF%BC%88%E4%B9%9F%E5%B1%9E%E4%BA%8E%E6%96%B9%E6%B3%95%E4%B8%80%EF%BC%89"><span class="toc-text">方式一：创建Thread匿名子类（也属于方法一）</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E5%BC%8F%E4%BA%8C%EF%BC%9A%E5%AE%9E%E7%8E%B0Runnable%E6%8E%A5%E5%8F%A3"><span class="toc-text">方式二：实现Runnable接口</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%AF%94%E8%BE%83%E5%88%9B%E5%BB%BA%E7%BA%BF%E7%A8%8B%E7%9A%84%E4%B8%A4%E7%A7%8D%E6%96%B9%E5%BC%8F"><span class="toc-text">比较创建线程的两种方式</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E5%BC%8F%E4%B8%89%EF%BC%9A%E5%AE%9E%E7%8E%B0Callable%E6%8E%A5%E5%8F%A3"><span class="toc-text">方式三：实现Callable接口</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E5%BC%8F%E5%9B%9B%EF%BC%9A%E7%BA%BF%E7%A8%8B%E6%B1%A0"><span class="toc-text">方式四：线程池</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E5%BC%8F%E4%BA%94%EF%BC%9ACompletableFuture"><span class="toc-text">方式五：CompletableFuture</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Thread%E7%B1%BB%E7%9A%84%E5%B8%B8%E7%94%A8%E6%96%B9%E6%B3%95"><span class="toc-text">Thread类的常用方法</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E7%BA%BF%E7%A8%8B%E7%9A%84%E8%B0%83%E5%BA%A6"><span class="toc-text">线程的调度</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#cpu%E7%9A%84%E8%B0%83%E5%BA%A6%E7%AD%96%E7%95%A5"><span class="toc-text">cpu的调度策略</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Java%E7%9A%84%E8%B0%83%E5%BA%A6%E7%AE%97%E6%B3%95%EF%BC%9A"><span class="toc-text">Java的调度算法：</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E7%BA%BF%E7%A8%8B%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F"><span class="toc-text">线程的生命周期</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%AD%A5%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3"><span class="toc-text">线程同步问题解决</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E5%BC%8F%E4%B8%80%EF%BC%9A%E5%90%8C%E6%AD%A5%E4%BB%A3%E7%A0%81%E5%9D%97"><span class="toc-text">方式一：同步代码块</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E5%BC%8F%E4%BA%8C%EF%BC%9A%E5%90%8C%E6%AD%A5%E6%96%B9%E6%B3%95"><span class="toc-text">方式二：同步方法</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8%E5%90%8C%E6%AD%A5%E8%A7%A3%E5%86%B3%E6%87%92%E6%B1%89%E6%A8%A1%E5%BC%8F%E7%9A%84%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E9%97%AE%E9%A2%98"><span class="toc-text">使用同步解决懒汉模式的线程安全问题</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%96%B9%E5%BC%8F%E4%B8%89%EF%BC%9ALock%E9%94%81-JDK5-0%E6%96%B0%E7%89%B9%E6%80%A7"><span class="toc-text">方式三：Lock锁 -JDK5.0新特性</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E7%BA%BF%E7%A8%8B%E7%9A%84%E9%80%9A%E4%BF%A1"><span class="toc-text">线程的通信</span></a></li></ol>
      
    </div>
  </div>

  
<script src="/js/catalog.js"></script>




    
      <div class="comments-container">
        




  
    <script async type="text/javascript" src="/plugins/valine.min.js" onload="loadValineSuc(this)"></script>
  

  <div id="vcomments"></div>

  <script>
    function loadValineSuc() {
      new Valine({
        el: '#vcomments',
        appId: 'H2QqshKF8elT2Si5bfKynT9h-9Nh9j0Va',
        appKey: 'WgtVppOWkTZ8fWNReNI1Ymf7',
        placeholder: '有问题请留言吧!',
        avatar: 'retro',
        lang: 'en'
      })
    }
  </script>

    <style>
      .comments-container .v .vempty {
        display: none!important;
      }
    </style>




      </div>
    
  </div>


        
<div class="footer">
  <div class="social">
    <ul>
      
        <li>
          <a title="github" target="_blank" rel="noopener" href="https://github.com/zchengsite/hexo-theme-oranges">
            <i class="iconfont icon-github"></i>
          </a>
        </li>
      
        <li>
          <a title="email" target="_blank" rel="noopener" href="https://c77544s.github.io/about/">
            <i class="iconfont icon-envelope"></i>
          </a>
        </li>
      
        <li>
          <a title="wechat" target="_blank" rel="noopener" href="https://c77544s.github.io/about/">
            <i class="iconfont icon-wechat"></i>
          </a>
        </li>
      
        <li>
          <a title="rss" href="/atom.xml">
            <i class="iconfont icon-rss"></i>
          </a>
        </li>
      
    </ul>
  </div>
  
    
    <div class="footer-more">
      
        <a target="_blank" rel="noopener" href="https://github.com/zchengsite/hexo-theme-oranges">Copyright © 2023 Oranges</a>
        
    </div>
  
    
    <div class="footer-more">
      
        <a target="_blank" rel="noopener" href="https://github.com/zchengsite/hexo-theme-oranges">Theme by Oranges | Powered by Hexo</a>
        
    </div>
  
  
</div>

      </div>

      <div class="tools-bar">
        <div class="back-to-top tools-bar-item hidden">
  <a href="javascript: void(0)">
    <i class="iconfont icon-chevronup"></i>
  </a>
</div>


<script src="/js/backtotop.js"></script>



        
  <div class="search-icon tools-bar-item" id="search-icon">
    <a href="javascript: void(0)">
      <i class="iconfont icon-search"></i>
    </a>
  </div>

  <div class="search-overlay hidden">
    <div class="search-content" tabindex="0">
      <div class="search-title">
        <span class="search-icon-input">
          <a href="javascript: void(0)">
            <i class="iconfont icon-search"></i>
          </a>
        </span>
        
          <input type="text" class="search-input" id="search-input" placeholder="搜索...">
        
        <span class="search-close-icon" id="search-close-icon">
          <a href="javascript: void(0)">
            <i class="iconfont icon-close"></i>
          </a>
        </span>
      </div>
      <div class="search-result" id="search-result"></div>
    </div>
  </div>

  <script type="text/javascript">
    var inputArea = document.querySelector("#search-input")
    var searchOverlayArea = document.querySelector(".search-overlay")

    inputArea.onclick = function() {
      getSearchFile()
      this.onclick = null
    }

    inputArea.onkeydown = function() {
      if(event.keyCode == 13)
        return false
    }

    function openOrHideSearchContent() {
      let isHidden = searchOverlayArea.classList.contains('hidden')
      if (isHidden) {
        searchOverlayArea.classList.remove('hidden')
        document.body.classList.add('hidden')
        // inputArea.focus()
      } else {
        searchOverlayArea.classList.add('hidden')
        document.body.classList.remove('hidden')
      }
    }

    function blurSearchContent(e) {
      if (e.target === searchOverlayArea) {
        openOrHideSearchContent()
      }
    }

    document.querySelector("#search-icon").addEventListener("click", openOrHideSearchContent, false)
    document.querySelector("#search-close-icon").addEventListener("click", openOrHideSearchContent, false)
    searchOverlayArea.addEventListener("click", blurSearchContent, false)

    var searchFunc = function (path, search_id, content_id) {
      'use strict';
      var $input = document.getElementById(search_id);
      var $resultContent = document.getElementById(content_id);
      $resultContent.innerHTML = "<ul><span class='local-search-empty'>First search, index file loading, please wait...<span></ul>";
      $.ajax({
        // 0x01. load xml file
        url: path,
        dataType: "xml",
        success: function (xmlResponse) {
          // 0x02. parse xml file
          var datas = $("entry", xmlResponse).map(function () {
            return {
              title: $("title", this).text(),
              content: $("content", this).text(),
              url: $("url", this).text()
            };
          }).get();
          $resultContent.innerHTML = "";

          $input.addEventListener('input', function () {
            // 0x03. parse query to keywords list
            var str = '<ul class=\"search-result-list\">';
            var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
            $resultContent.innerHTML = "";
            if (this.value.trim().length <= 0) {
              return;
            }
            // 0x04. perform local searching
            datas.forEach(function (data) {
              var isMatch = true;
              var content_index = [];
              if (!data.title || data.title.trim() === '') {
                data.title = "Untitled";
              }
              var orig_data_title = data.title.trim();
              var data_title = orig_data_title.toLowerCase();
              var orig_data_content = data.content.trim().replace(/<[^>]+>/g, "");
              var data_content = orig_data_content.toLowerCase();
              var data_url = data.url;
              var index_title = -1;
              var index_content = -1;
              var first_occur = -1;
              // only match artiles with not empty contents
              if (data_content !== '') {
                keywords.forEach(function (keyword, i) {
                  index_title = data_title.indexOf(keyword);
                  index_content = data_content.indexOf(keyword);

                  if (index_title < 0 && index_content < 0) {
                    isMatch = false;
                  } else {
                    if (index_content < 0) {
                      index_content = 0;
                    }
                    if (i == 0) {
                      first_occur = index_content;
                    }
                    // content_index.push({index_content:index_content, keyword_len:keyword_len});
                  }
                });
              } else {
                isMatch = false;
              }
              // 0x05. show search results
              if (isMatch) {
                str += "<li><a href='" + data_url + "' class='search-result-title'>" + orig_data_title + "</a>";
                var content = orig_data_content;
                if (first_occur >= 0) {
                  // cut out 100 characters
                  var start = first_occur - 20;
                  var end = first_occur + 80;

                  if (start < 0) {
                    start = 0;
                  }

                  if (start == 0) {
                    end = 100;
                  }

                  if (end > content.length) {
                    end = content.length;
                  }

                  var match_content = content.substr(start, end);

                  // highlight all keywords
                  keywords.forEach(function (keyword) {
                    var regS = new RegExp(keyword, "gi");
                    match_content = match_content.replace(regS, "<span class=\"search-keyword\">" + keyword + "</span>");
                  });

                  str += "<p class=\"search-result-abstract\">" + match_content + "...</p>"
                }
                str += "</li>";
              }
            });
            str += "</ul>";
            if (str.indexOf('<li>') === -1) {
              return $resultContent.innerHTML = "<ul><span class='local-search-empty'>No result<span></ul>";
            }
            $resultContent.innerHTML = str;
          });
        },
        error: function(xhr, status, error) {
          $resultContent.innerHTML = ""
          if (xhr.status === 404) {
            $resultContent.innerHTML = "<ul><span class='local-search-empty'>The search.xml file was not found, please refer to：<a href='https://github.com/zchengsite/hexo-theme-oranges#configuration' target='_black'>configuration</a><span></ul>";
          } else {
            $resultContent.innerHTML = "<ul><span class='local-search-empty'>The request failed, Try to refresh the page or try again later.<span></ul>";
          }
        }
      });
      $(document).on('click', '#search-close-icon', function() {
        $('#search-input').val('');
        $('#search-result').html('');
      });
    }

    var getSearchFile = function() {
        var path = "/search.xml";
        searchFunc(path, 'search-input', 'search-result');
    }
  </script>




        
  <div class="tools-bar-item theme-icon" id="switch-color-scheme">
    <a href="javascript: void(0)">
      <i id="theme-icon" class="iconfont icon-moon"></i>
    </a>
  </div>

  
<script src="/js/colorscheme.js"></script>





        
  
    <div class="share-icon tools-bar-item">
      <a href="javascript: void(0)" id="share-icon">
        <i class="iconfont iconshare"></i>
      </a>
      <div class="share-content hidden">
        
          <a class="share-item" href="https://twitter.com/intent/tweet?text=' + Java%E5%A4%9A%E7%BA%BF%E7%A8%8B + '&url=' + http%3A%2F%2Fc77544s.gitee.io%2F2021%2F08%2F23%2F%25E5%2590%258E%25E7%25AB%25AF%2FJava%2FJava%25E5%25A4%259A%25E7%25BA%25BF%25E7%25A8%258B%2F + '" target="_blank" title="Twitter">
            <i class="iconfont icon-twitter"></i>
          </a>
        
        
          <a class="share-item" href="https://www.facebook.com/sharer.php?u=http://c77544s.gitee.io/2021/08/23/%E5%90%8E%E7%AB%AF/Java/Java%E5%A4%9A%E7%BA%BF%E7%A8%8B/" target="_blank" title="Facebook">
            <i class="iconfont icon-facebooksquare"></i>
          </a>
        
      </div>
    </div>
  
  
<script src="/js/shares.js"></script>



      </div>
    </div>
  </body>
</html>
